﻿namespace ClassyBlog.Infrastructure.Specs.Unit
{
    using System;
    using System.Collections.Generic;
    using System.Reflection;
    using System.Web;
    using System.Web.Mvc;

    using Machine.Specifications;
    using NSubstitute;

    using DataAccess;
    using DomainObjects;
    using Infrastructure;
    using Web;

    [Subject(typeof(ServiceRegistrations))]
    public class when_creating_service_registration_with_blank_data_directory
    {
        static Exception exception;

        Because of = () => exception =
            Catch.Exception(() =>
                new ServiceRegistrations(
                    null, Substitute.For<IServiceContainer>()));

        It should_throw_exception = () =>
            exception.ShouldBeOfType<ArgumentException>();
    }

    [Subject(typeof(ServiceRegistrations))]
    public class when_creating_service_registration_with_null_container
    {
        static Exception exception;

        Because of = () => exception =
            Catch.Exception(() => new ServiceRegistrations("App_Data", null));

        It should_throw_exception = () =>
            exception.ShouldBeOfType<ArgumentNullException>();
    }

    [Subject(typeof(ServiceRegistrations))]
    public class when_services_are_registered
    {
        static IServiceContainer container;

        Establish context = () => container = new ServiceContainer();

        Because of = () =>
        {
            new ServiceRegistrations("App_Data", container).Register();
            container.RegisterAsSingleton<IBuildManager>(c =>
                new TestEnvironmenBuildManager());
        };

        It should_register_build_manager = () =>
            container.Resolve<IBuildManager>()
                     .ShouldBeOfType<TestEnvironmenBuildManager>();

        It should_register_file_system = () =>
            container.Resolve<IFileSystem>().ShouldBeOfType<FileSystem>();

        It should_register_http = () =>
            container.Resolve<IHttp>().ShouldBeOfType<Http>();

        It should_register_file_resolver = () =>
            container.Resolve<IPathResolver>().ShouldBeOfType<PathResolver>();

        It should_register_page_factory = () =>
            container.Resolve<IArticleFactory<Page>>()
                     .ShouldBeOfType<PageFactory>();

        It should_register_post_factory = () =>
            container.Resolve<IArticleFactory<Post>>()
                     .ShouldBeOfType<PostFactory>();

        It should_register_lazy_http_context = () =>
            container.Resolve<Func<HttpContextBase>>().ShouldNotBeNull();

        It should_register_page_repository = () =>
            container.Resolve<IPageRepository>()
                     .ShouldBeOfType<PageRepository>();

        It should_register_post_repository = () =>
            container.Resolve<IPostRepository>()
                     .ShouldBeOfType<PostRepository>();

        It should_register_blog_repository = () =>
            container.Resolve<IBlogRepository>()
                     .ShouldBeOfType<BlogRepository>();

        It should_register_pages_controller = () =>
            container.Resolve<PagesController>()
                     .ShouldBeOfType<PagesController>();

        It should_register_posts_controller = () =>
            container.Resolve<PostsController>()
                     .ShouldBeOfType<PostsController>();

        It should_register_content_proxy_controller = () =>
            container.Resolve<ContentProxyController>()
                     .ShouldBeOfType<ContentProxyController>();

        It should_register_current_blog_provider = () =>
            container.Resolve<ICurrentBlogProvider>()
                     .ShouldBeOfType<CurrentBlogProvider>();

        It should_register_current_blog = () =>
            container.Resolve<CurrentBlog>().ShouldBeOfType<CurrentBlog>();

        It should_register_view_page_activator = () =>
            container.Resolve<IViewPageActivator>()
                     .ShouldBeOfType<DefaultViewPageActivator>();

        It should_register_renderer = () =>
            container.Resolve<IRenderer>().ShouldBeOfType<Renderer>();

        It should_register_null_formatter = () =>
            container.Resolve<NullFormatter>().ShouldBeOfType<NullFormatter>();

        It should_register_markdown_formatter = () =>
            container.Resolve<MarkdownFormatter>()
                     .ShouldBeOfType<MarkdownFormatter>();

        It should_register_textile_formatter = () =>
            container.Resolve<TextileFormatter>()
                     .ShouldBeOfType<TextileFormatter>();

        It should_register_formatters = () =>
            container.Resolve<IEnumerable<IFormatter>>()
                     .ShouldBeOfType<IList<IFormatter>>();

        It should_register_macro_runner = () =>
            container.Resolve<IMacroRunner>()
                     .ShouldBeOfType<MacroRunner>();

        private sealed class TestEnvironmenBuildManager : DefaultBuildManager
        {
            public override IEnumerable<Assembly> PrivateAssemblies
            {
                get
                {
                    return new[]
                               {
                                   typeof(Disposable).Assembly,
                                   typeof(DefaultBuildManager).Assembly
                               };
                }
            }
        }
    }

    [Subject(typeof(ServiceRegistrations))]
    public class when_depency_resolver_is_set
    {
        static IServiceContainer container;

        Establish context = () => container = new ServiceContainer();

        Because of = () =>
            new ServiceRegistrations("App_Data", container).Register();

        It should_set_current_depedency_resolver = () =>
            DependencyResolver.Current
                              .ShouldBeOfType<DefaultDependencyResolver>();
    }
}